package com.fs.uc.api.admin.resource;

import com.fs.uc.api.admin.dto.CustomUserRole;
import com.fs.uc.api.admin.dto.DtoRole;
import com.fs.uc.api.admin.dto.ReqBindRoles;
import com.fs.uc.api.admin.dto.ReqOpenAuthorityByTenantAdmin;
import com.fs.uc.base.Const;
import com.fs.uc.core.SubjectType;
import com.fs.uc.core.behavior.ParkBehavior;
import com.fs.uc.core.relationship.IRelationFetcher;
import com.fs.uc.core.relationship.RelationFetcherFactory;
import com.fs.uc.security.Auth;
import com.fs.uc.security.AuthContext;
import com.fs.uc.base.domain.AdditionalRole;
import com.fs.uc.base.domain.Role;
import com.fs.uc.base.repo.AdditionalRoleRepository;
import com.fs.uc.base.repo.RoleRepository;

import javax.enterprise.context.ApplicationScoped;
import javax.transaction.Transactional;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 园区组织管理员api,需要鉴权
 *
 * @author 崔超
 * 2021/12/2
 */
@ApplicationScoped
@Path(Const.URL_PREFIX + "/admin")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Transactional
@Auth
public class ParkAdminResource {

    private final AdditionalRoleRepository additionalRoleRepo;
    private final ParkBehavior parkBehavior;
    private final IRelationFetcher relationFetcher;

    public ParkAdminResource(AdditionalRoleRepository additionalRoleRepo, ParkBehavior parkBehavior, RelationFetcherFactory rfFactory) {
        this.additionalRoleRepo = additionalRoleRepo;
        this.parkBehavior = parkBehavior;
        this.relationFetcher = rfFactory.fetcher(SubjectType.Org);
    }

    /*
    查询组织下可以被分配的角色
     */
    @Path("/roles")
    @GET
    public List<DtoRole> getSystemRoles() {
        Long parkId = fetchParkId(AuthContext.getSubjectType(), AuthContext.getSubjectId());
        return parkBehavior.getAssignableRoles(parkId).stream()
                .map(role -> new DtoRole(role.id.toString(), role.name, role.humanName))
                .collect(Collectors.toList());
    }

    /*
    查询某个自定义用户的系统角色分配状态（通过网关调用，参数userId需换为id(主键)）
     */
    @GET
    @Path("/systemRole")
    public List<CustomUserRole> getSystemRolesOfUser(@NotNull @QueryParam("userId") Long userId) {
        Long parkId = fetchParkId(AuthContext.getSubjectType(), AuthContext.getSubjectId());
        Set<Role> additionalRolesOfOrg = parkBehavior.getAssignableRoles(parkId);
        List<Long> roleIdsOfUser = additionalRoleRepo.findRoleIds(parkId, userId);

        return additionalRolesOfOrg.stream().map(sysRole -> {
            boolean isBind = roleIdsOfUser.stream().anyMatch(roleId -> Objects.equals(roleId, sysRole.id));
            return new CustomUserRole(sysRole.id.toString(), sysRole.name, sysRole.humanName, isBind);
        }).collect(Collectors.toList());
    }

    /*
    绑定自定义用户角色（通过网关调用，参数userId需换为id(主键)
     */
    @POST
    @Path("/roles")
    public void bindSystemRoles(@Valid ReqBindRoles req) {
        Long parkId = fetchParkId(AuthContext.getSubjectType(), AuthContext.getSubjectId());
        parkBehavior.bindAdditionalRole(parkId, req.getUserId(), req.getRoleNames());
    }

    /*
    开通零圆模块授权
     */
    @POST
    @Path("/module")
    public void openModule(@Valid ReqOpenAuthorityByTenantAdmin req) {
        Long parkId = fetchParkId(AuthContext.getSubjectType(), AuthContext.getSubjectId());
        parkBehavior.enableFunction(parkId, req.getAapModuleName());
    }

    @DELETE
    @Path("/module")
    public void closeModule(@Valid @NotNull ReqOpenAuthorityByTenantAdmin req) {
        Long parkId = fetchParkId(AuthContext.getSubjectType(), AuthContext.getSubjectId());
        parkBehavior.disableFunction(parkId, req.getAapModuleName());
    }

    private Long fetchParkId(SubjectType type, Long subjectId) {
        if (type != SubjectType.Org) {
            throw new RuntimeException("令牌主体类型非组织");
        }
        return relationFetcher.inWhichPark(subjectId);
    }

}
